package com.ctakit.sdk.app.util;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;


import com.ctakit.sdk.SdkApplication;
import com.ctakit.sdk.app.BuildConfig;
import com.ctakit.sdk.util.Base64;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.UUID;

public class DeviceUtil {
    private static final String TAG = "DeviceUtil";
    private static final boolean DEBUG = BuildConfig.DEBUG;

    public static final String DEVICE_ID = "device_id";

    private static String deviceID = null;

    private static int statusBarHeight = 0;

    public static final String getDeviceID() {
        synchronized (DeviceUtil.class) {
            if (deviceID != null)
                return deviceID;
            Context context = SdkApplication.app();
            deviceID = SharedPreferenceUtil.getString(DEVICE_ID, "");


            if (!TextUtils.isEmpty(deviceID)) {
                deviceID = new String(Base64.decode(deviceID, Base64.DEFAULT));

                return deviceID;
            }
            if (DEBUG) {
                Log.i(TAG, "getDeviceID: getting device id for the first time");
            }

            deviceID = getDeviceIDInner(context);
            deviceID = StringUtil.hashKey(deviceID);

            String di = new String(Base64.encode(deviceID.getBytes(), Base64.DEFAULT));
            SharedPreferenceUtil.putStringValueByKey(DEVICE_ID, di);

            return deviceID;
        }
    }

    private synchronized static final String getDeviceIDInner(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        String deviceID = null;
        try {
            deviceID = telephonyManager.getDeviceId();
        } catch (Exception e) {

        }
        if (deviceID != null)
            return deviceID;
        if (BuildConfig.DEBUG)
            Log.e(TAG, "getDeviceID: failed to get from telephonyManager");

//        WifiManager wifiManager = (WifiManager) context
//                .getSystemService(Context.WIFI_SERVICE);
//        try {
//            String mac = wifiManager.getConnectionInfo().getMacAddress();
//            if (mac != null)
//                return mac;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        String mac  = getMacAddress(context);
        if (mac != null) return mac;

        if (BuildConfig.DEBUG)
            Log.e(TAG, "getDeviceID: failed to get mac");

        String androidID = Secure.getString(context.getContentResolver(),
                Secure.ANDROID_ID);
        if (androidID != null)
            return androidID;
        if (BuildConfig.DEBUG)
            Log.e(TAG, "getDeviceID: failed to get andorid id");

        if (BuildConfig.DEBUG)
            Log.i(TAG,
                    "getDeviceID: using uuid. If you see this, do not feel happy");
        String uuid = UUID.randomUUID().toString();
        return uuid;
    }

    public static final String getDeviceInfo() {
        StringBuilder b = new StringBuilder();

        b.append("Build.BOARD" + ":" + Build.BOARD);
        b.append("Build.BRAND" + ":" + Build.BRAND);
        b.append("Build.CPU_ABI" + ":" + Build.CPU_ABI);
        b.append("Build.DEVICE" + ":" + Build.DEVICE);
        b.append("Build.DISPLAY" + ":" + Build.DISPLAY);
        b.append("Build.FINGERPRINT" + ":" + Build.FINGERPRINT);
        b.append("Build.HOST" + ":" + Build.HOST);
        b.append("Build.ID" + ":" + Build.ID);
        b.append("Build.MANUFACTURER" + ":" + Build.MANUFACTURER);
        b.append("Build.MODEL" + ":" + Build.MODEL);
        b.append("Build.PRODUCT" + ":" + Build.PRODUCT);
        b.append("Build.TAGS" + ":" + Build.TAGS);
        b.append("Build.USER" + ":" + Build.USER);
        b.append("Build.VERSION.CODENAME" + ":" + Build.VERSION.CODENAME);
        b.append("Build.VERSION.INCREMENTAL" + ":" + Build.VERSION.INCREMENTAL);
        b.append("Build.VERSION.RELEASE" + ":" + Build.VERSION.RELEASE);
        b.append("Build.VERSION.SDK_INT" + ":" + Build.VERSION.SDK_INT);

        return b.toString();
    }

    public static final String getDeviceName() {
        StringBuilder stringBuilder = new StringBuilder();
        String deviceBrand = Build.BRAND;
        if (deviceBrand == null) {
            deviceBrand = Build.MANUFACTURER;
        }
        if (deviceBrand == null) {
            deviceBrand = "Android";
        }

        String deviceModel = Build.MODEL;
        if (deviceModel == null) {
            deviceModel = "";
        }

        String release = Build.VERSION.RELEASE;
        if (release == null) {
            release = "sdk " + Build.VERSION.SDK_INT;
        }

        stringBuilder.append(deviceBrand);
        stringBuilder.append(" ");
        stringBuilder.append(deviceModel);
        stringBuilder.append(" ");
        stringBuilder.append(release);
        return stringBuilder.toString();
    }

    public static int getStatusBarHeight(Activity activity) {
        if (statusBarHeight > 0)
            return statusBarHeight;
        if (activity == null)
            return 0;

        int x = 0;
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            statusBarHeight = activity.getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (DEBUG)
            Log.v(TAG, "getStatusBarHeight: from com.android.internal.R$dimen "
                    + statusBarHeight);
        if (statusBarHeight <= 0) {
            Rect frame = new Rect();
            activity.getWindow().getDecorView()
                    .getWindowVisibleDisplayFrame(frame);
            statusBarHeight = frame.top;

            if (DEBUG)
                Log.v(TAG, "getStatusBarHeight: from DecorView "
                        + statusBarHeight);
        }
        return statusBarHeight;
    }


    /**
     * 获取MAC地址
     *
     * @param context
     * @return
     */
    private static String getMacAddress(Context context) {
        String mac = null;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            mac = getMacDefault(context);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            mac = getMacFromFile();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mac = getMacFromHardware();
        }
        if (StringUtil.isEmptyString(mac) || "02:00:00:00:00:00".equals(mac)){
            return null;
        }
        return mac;
    }

    /**
     * Android  6.0 之前（不包括6.0）
     * 必须的权限  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     * @param context
     * @return
     */
    private static String getMacDefault(Context context) {
        String mac = "02:00:00:00:00:00";
        if (context == null) {
            return mac;
        }

        WifiManager wifi = (WifiManager) context.getApplicationContext()
                .getSystemService(Context.WIFI_SERVICE);
        if (wifi == null) {
            return mac;
        }
        WifiInfo info = null;
        try {
            info = wifi.getConnectionInfo();
        } catch (Exception e) {
        }
        if (info == null) {
            return null;
        }
        mac = info.getMacAddress();
        if (!TextUtils.isEmpty(mac)) {
            mac = mac.toUpperCase(Locale.ENGLISH);
        }
        return mac;
    }

    /**
     * Android 6.0（包括） - Android 7.0（不包括）
     * @return
     */
    private static String getMacFromFile() {
        try {
           String mac = new BufferedReader(new FileReader(new File("/sys/class/net/wlan0/address"))).readLine();
           return mac;
        } catch (IOException e) {
            return "02:00:00:00:00:00";
        }
    }

    /**
     * 遍历循环所有的网络接口，找到接口是 wlan0
     * 必须的权限 <uses-permission android:name="android.permission.INTERNET" />
     * @return
     */
    private static String getMacFromHardware() {
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

                byte[] macBytes = nif.getHardwareAddress();
                if (macBytes == null) {
                    return "";
                }

                StringBuilder res1 = new StringBuilder();
                for (byte b : macBytes) {
                    res1.append(String.format("%02X:", b));
                }

                if (res1.length() > 0) {
                    res1.deleteCharAt(res1.length() - 1);
                }
                return res1.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "02:00:00:00:00:00";
    }

}
